﻿using System;
using System.Collections.Generic;
using System.Data;
using accesoDatos;

namespace Logica
{
    public class Producto : EntidadAlmacenable
    {
        /* --------------------- Atributos de la clase. Recordar que hay atributos heredados --------------------- */
        private String nombre = "", descripcion = "";
        private int codigoInterno = 0, estuchesPorCaja=0;

        private List<CaractLoteProducto> caracteristicas;
        private List<Formula> formulas;

        public const string tablaBD = "producto", columnaID = "id";


        /* --------------------- Propiedades --------------------- */
        public int ID
        {
            get { return this.id; }
            set { this.id = value; }
        }

        public String Nombre
        {
            get { return nombre; }
            set { nombre = value; }
        }

        public String Descripcion
        {
            get { return descripcion; }
            set { descripcion = value; }
        }

        public int CodigoInterno
        {
            get { return codigoInterno; }
            set { codigoInterno = value; }
        }

        public int EstuchesPorCaja
        {
            get { return estuchesPorCaja; }
            set { estuchesPorCaja = value; }
        }

        public List<CaractLoteProducto> Caracteristicas
        {
            get { return caracteristicas; }
            set { caracteristicas = value; }
        }

        public List<Formula> Formulas
        {
            get { return formulas; }
            set { formulas = value; }
        }


        /* --------------------- Constructores --------------------- */
        public Producto()
            : this(0, true) // Llamo al constructor que recibe un parámetro para reutilizar el código del mismo
        { }

        public Producto(int idElem)
            : this(idElem, true) // Llamo al constructor que recibe un parámetro para reutilizar el código del mismo
        { }

        /* IMPORTANTE:
             ** Si el campo identificador unívoco de la tabla actual tuviese un nombre distinto de "id", se lo debe setear en este momento
             * (atributo heredado: nombreColumnaID)
             ** Si el campo identificador unívoco NO se generase automáticamente, se lo debe definir en este momento, cambiando el atributo
             * heredado idAutoGenerado por FALSE.
             */
        public Producto(int idElem, bool cargarListas)
            : base() // Llamo al constructor padre en primer lugar, para inicializar los valores correspondientes
        {
            // Es importante esta asignación ya que estos valores se utilizan tanto en métodos del objeto padre como éste
            this.nombreTablaBD = tablaBD;
            this.nombreColumnaID = columnaID;
            this.id = idElem;

            this.relacionesOtrasTablas.Add(Formula.tablaBD, "idProducto");
            this.relacionesOtrasTablas.Add(CaractLoteProducto.tablaBD, "idProducto");

            // Si se hubiese enviado un id != 0, entonces se buscan los datos del elemento en la BD para cargarlos al objeto actual que se está creando
            if (this.id != 0)
            {
                DataRow elemento = this.buscarElemento(id);
                try
                {
                    this.nombre = elemento["nombre"].ToString().Trim();
                    this.descripcion = elemento["descripcion"].ToString().Trim();
                    this.codigoInterno = Convert.ToInt32(elemento["codigoInterno"]);
                    this.estuchesPorCaja = Convert.ToInt32(elemento["estuchesPorCaja"]);
                }
                catch (Exception ex)
                {
                    this.error = ex.Message;
                }
            }

            if (cargarListas) cargarColecciones();
            else
            {
                this.caracteristicas = new List<CaractLoteProducto>();
                this.formulas = new List<Formula>();
            }
        }

        public void cargarColecciones()
        {
            this.caracteristicas = CaractLoteProducto.listar(new string[] { "idProducto" }, new string[] { "E" + this.id.ToString() });
            this.formulas = Formula.listar(new string[] { "idProducto" }, new string[] { "E" + this.id.ToString() });
        }


        /* --------------------- Métodos --------------------- */
        public Formula obtenerFormulaActual()
        {
            Formula formActual = this.formulas.Find(elem => elem.FormulaActual);
            if (formActual == null) formActual = new Formula();

            return formActual;
        }

        public static int obtenerIdFormulaActual(int idProd)
        {
            ManejadorBD manejadorBD = new ManejadorBD();

            string consultaSQL = string.Format("SELECT {0} FROM {1} WHERE idProducto = '{2}' and formulaActual = 1",
                Formula.columnaID, Formula.tablaBD, idProd);
            int idForm = manejadorBD.obtenerNumeroEntero(consultaSQL);
            return idForm;
        }
        
        public static bool existe(int id, string nombre)
        {
            string[] camposFiltro = new string[] { columnaID, "nombre" };
            string[] valoresFiltro = new string[] { "E" + id.ToString(), "E" + nombre.Trim() };

            return Producto.existeElemento(Producto.tablaBD, camposFiltro, valoresFiltro);
        }

        public String guardar()
        {
            String[] columnas = new String[] { columnaID, "nombre", "descripcion", "codigoInterno", "estuchesPorCaja" };
            String[] valores = new String[] { this.id.ToString(), this.nombre.Trim().ToUpper(), this.descripcion.Trim(), this.codigoInterno.ToString(), this.estuchesPorCaja.ToString() };

            string error = base.guardarElemento(columnas, valores);
            if (error.Equals(""))
            {
                string errorCaract = "";
                foreach (CaractLoteProducto caract in this.caracteristicas)
                {
                    // Si se tratase de un producto nuevo, el id del mismo acaba de generarse, con lo cual tengo que asegurarme de 
                    // guardar el que corresponda. Si fuera una modificación, se mantiene.
                    caract.IdProducto = this.id;
                    errorCaract = " " + caract.guardar();
                }
                if (!errorCaract.Trim().Equals("")) error += "Errores ocurridos al insertar los ítems: " + errorCaract;
            }

            return error;
        }
    }
}
